feat: add Vertex AI provider to api-proxy credential isolation (port 10004)#5878
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new Google Vertex AI (Vertex mode for Gemini CLI) credential-isolation path to the AWF api-proxy sidecar, so GOOGLE_API_KEY stays in the sidecar and Vertex traffic is routed through the proxy for telemetry and policy enforcement.
Changes:
- Introduces a new api-proxy provider adapter for Vertex AI on port
10004and wires it into the sidecar provider registry. - Adds host-side config/env plumbing for
GOOGLE_API_KEY(sidecar) +GOOGLE_VERTEX_BASE_URL(agent placeholder routing), plus routing override fields (vertexApiTarget/vertexApiBasePath). - Extends credential-isolation exclusions, home directory mounts, and unit tests to cover the new provider.
Show a summary per file
| File | Description |
|---|---|
| src/workdir-setup.ts | Mount/precreate .gemini when googleApiKey is present. |
| src/types/ports.ts | Adds API_PROXY_PORTS.VERTEX = 10004. |
| src/types/api-proxy-routing-options.ts | Adds Vertex routing override fields (vertexApiTarget, vertexApiBasePath). |
| src/types/api-proxy-credential-options.ts | Adds googleApiKey?: string and documents Vertex env behavior. |
| src/services/credentials/vertex-credential-env.ts | Injects GOOGLE_VERTEX_BASE_URL + placeholder GOOGLE_API_KEY into agent env. |
| src/services/api-proxy-service-split.test.ts | Adds unit test coverage for Vertex agent env injection. |
| src/services/api-proxy-env-config.ts | Forwards Vertex target/basePath and GOOGLE_API_KEY into sidecar env. |
| src/services/api-proxy-credential-env.ts | Includes Vertex credential env builder in agent additions. |
| src/services/agent-volumes/home-strategy.ts | Mounts .gemini when googleApiKey is present. |
| src/services/agent-environment/excluded-vars.ts | Excludes GOOGLE_API_KEY / GOOGLE_VERTEX_BASE_URL from agent passthrough when api-proxy enabled. |
| src/services/agent-environment/excluded-vars.test.ts | Adds tests for new excluded env vars. |
| src/security-module-coverage.test.ts | Adds coverage checks for buildVertexCredentialEnv. |
| src/commands/validators/config-assembly.ts | Includes Vertex in api-proxy validation/logging. |
| src/commands/resolve-credentials.ts | Resolves googleApiKey and Vertex routing overrides from env/options. |
| src/commands/resolve-credentials.test.ts | Tests GOOGLE_API_KEY + Vertex override env parsing. |
| src/commands/main-action.ts | Marks googleApiKey as sensitive for redaction. |
| src/commands/build-config.test.ts | Tests that GOOGLE_API_KEY is read into config. |
| src/api-proxy-env-constants.ts | Exports VERTEX_ENV from shared constants. |
| src/api-proxy-env-constants-sync.test.ts | Ensures TS constants stay in sync with sidecar JSON. |
| src/api-proxy-config-validation.ts | Updates “no keys found” warnings and debug messages to include Vertex key. |
| containers/api-proxy/providers/vertex.js | Implements Vertex provider adapter (port 10004, x-goog-api-key). |
| containers/api-proxy/providers/index.js | Registers Vertex adapter in createAllAdapters(). |
| containers/api-proxy/provider-env-constants.json | Adds VERTEX_ENV mapping for env var names. |
| containers/api-proxy/Dockerfile | Exposes port 10004 for the new provider. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 24/24 changed files
- Comments generated: 3
- Review effort level: Low
| const hostHomeMountSourceDirs = [ | ||
| '.copilot', '.cache', '.config', '.local', | ||
| '.anthropic', '.claude', '.cargo', '.rustup', '.npm', '.nvm', | ||
| ...(config.geminiApiKey ? ['.gemini'] : []), | ||
| ...(config.geminiApiKey || config.googleApiKey ? ['.gemini'] : []), | ||
| ]; |
| * Can be set via: | ||
| * - CLI flag: `--vertex-api-target <host>` | ||
| * - Environment variable: `VERTEX_API_TARGET` | ||
| * |
| # 10001 - Anthropic API proxy | ||
| # 10002 - GitHub Copilot API proxy | ||
| # 10003 - Google Gemini API proxy | ||
| EXPOSE 10000 10001 10002 10003 | ||
| # 10004 - Google Vertex AI API proxy | ||
| EXPOSE 10000 10001 10002 10003 10004 |
|
@copilot address review feedback |
|
✅ Copilot review passed with no inline comments. @copilot Add the |
|
| Metric | Base | PR | Delta |
|---|---|---|---|
| Lines | 98.61% | 98.63% | 📈 +0.02% |
| Statements | 98.53% | 98.55% | 📈 +0.02% |
| Functions | 99.43% | 99.44% | ➡️ +0.01% |
| Branches | 94.37% | 94.34% | 📉 -0.03% |
📁 Per-file Coverage Changes (3 files)
| File | Lines (Before → After) | Statements (Before → After) |
|---|---|---|
src/api-proxy-config-validation.ts |
100.0% → 96.0% (-4.00%) | 100.0% → 96.0% (-4.00%) |
src/api-proxy-config-domains.ts |
100.0% → 100.0% (+0.00%) | 98.8% → 98.9% (+0.05%) |
src/workdir-setup.ts |
93.0% → 94.9% (+1.87%) | 93.0% → 94.9% (+1.87%) |
✨ New Files (1 files)
src/services/credentials/vertex-credential-env.ts: 100.0% lines
Coverage comparison generated by scripts/ci/compare-coverage.ts
|
@copilot address this failing ci check https://github.com/github/gh-aw-firewall/actions/runs/28675505924/job/85048023189?pr=5878 |
Fixed in 1647f92. I reproduced the failing Build Verification job locally and updated the API proxy unit tests to include the new Vertex provider (5 providers/endpoints, vertex fallback entry, port 10004, and null models_url expectation). |
|
| Metric | Base | PR | Delta |
|---|---|---|---|
| Lines | 98.61% | 98.63% | 📈 +0.02% |
| Statements | 98.53% | 98.55% | 📈 +0.02% |
| Functions | 99.43% | 99.44% | ➡️ +0.01% |
| Branches | 94.37% | 94.34% | 📉 -0.03% |
📁 Per-file Coverage Changes (3 files)
| File | Lines (Before → After) | Statements (Before → After) |
|---|---|---|
src/api-proxy-config-validation.ts |
100.0% → 96.0% (-4.00%) | 100.0% → 96.0% (-4.00%) |
src/api-proxy-config-domains.ts |
100.0% → 100.0% (+0.00%) | 98.8% → 98.9% (+0.05%) |
src/workdir-setup.ts |
93.0% → 94.9% (+1.87%) | 93.0% → 94.9% (+1.87%) |
✨ New Files (1 files)
src/services/credentials/vertex-credential-env.ts: 100.0% lines
Coverage comparison generated by scripts/ci/compare-coverage.ts
Copilot Smoke Test — PASS
Overall: PASS — Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
Smoke Test: Claude Engine Validation
Overall Result: PASS Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
🔥 Smoke Test Results
Overall: PASS · Auth mode: PAT (COPILOT_GITHUB_TOKEN) cc Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
Smoke Test: Services Connectivity
Overall: FAIL — Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
|
Smoke Test: Copilot BYOK (Direct) Mode ✅ PASS
Running in direct BYOK mode via api-proxy sidecar. All systems operational. Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
|
$(sed s///g /tmp/gh-aw/agent/comment_body.txt) Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
|
Smoke test results:\n- fix: make test-coverage-reporter resilient to test failures ✅\n- fix: Copilot Business 'token' prefix not overridable by AWF_PLATFORM_TYPE ✅\n- Browser title contains GitHub ✅\n- File write/read ✅\n- Discussion comment Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"
- "registry.npmjs.org"See Network Configuration for more information.
|
Smoke Test Results: Gemini Engine
Overall Status: FAIL Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "localhost"See Network Configuration for more information.
|
|
PR Titles: ${{ steps.smoke-data.outputs.SMOKE_PR_DATA }} PASS
Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
Smoke Test: API Proxy OpenTelemetry Tracing
Overall: ✅ All scenarios pass (or behave as expected during development). Warning Firewall blocked 4 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "127.0.0.1"
- "api.example.com"
- "api.openai.com"
- "awmgmcpg"See Network Configuration for more information.
|
🏗️ Build Test Suite Results
Overall: 8/8 ecosystems passed — ✅ PASS
Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
PR #5878 (feat: add Vertex AI provider to api-proxy) introduced three new routing fields — vertexApiTarget, vertexApiBasePath — and the googleApiKey credential, but did not propagate the routing fields to all required config layers. Gaps fixed: - src/awf-config-schema.json: add targets.vertex providerTarget entry - docs/awf-config.schema.json: keep identical to src schema (synced) - src/config-file.ts: add vertex?: { host, basePath } to AwfFileConfig.apiProxy.targets - src/config-mapper.ts: map targets.vertex.host → vertexApiTarget and targets.vertex.basePath → vertexApiBasePath - docs/awf-config-spec.md: add CLI mapping rows for vertex.host and vertex.basePath Note: googleApiKey is security-sensitive and is correctly passed only via environment variable (GOOGLE_API_KEY), not via stdin config, so no change to config-file.ts for that field. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PR #5878 added Google Vertex AI provider (port 10004) to the api-proxy but missed updating docs/awf-config-spec.md. Gaps fixed: - §9.1 Source Credentials table: add GOOGLE_API_KEY → Google Vertex AI - §9.2.4 Proxy-routing variables table: add GOOGLE_VERTEX_BASE_URL → port 10004 - §9.2.5 Port assignments paragraph: add 10004 (Vertex AI) - §10.6 and introspection sections (§11.3, §11a.3, §11b.3): update port range 10000–10003 → 10000–10004 No schema changes needed (src/awf-config-schema.json already has apiProxy.targets.vertex and is identical to docs/awf-config.schema.json). TypeScript types and env-var wiring were correct in the original PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PR #5878 added Google Vertex AI provider (port 10004) to the api-proxy but missed updating docs/awf-config-spec.md. Gaps fixed: - §9.1 Source Credentials table: add GOOGLE_API_KEY → Google Vertex AI - §9.2.4 Proxy-routing variables table: add GOOGLE_VERTEX_BASE_URL → port 10004 - §9.2.5 Port assignments paragraph: add 10004 (Vertex AI) - §10.6 and introspection sections (§11.3, §11a.3, §11b.3): update port range 10000–10003 → 10000–10004 No schema changes needed (src/awf-config-schema.json already has apiProxy.targets.vertex and is identical to docs/awf-config.schema.json). TypeScript types and env-var wiring were correct in the original PR. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GOOGLE_API_KEY(Vertex AI mode) had no proxy path — the real key either leaked into the agent sandbox or caused gemini-cli startup failures, and all Vertex traffic bypassed the api-proxy so token/cost telemetry was never emitted.Changes
New Vertex AI provider adapter (
containers/api-proxy/providers/vertex.js)10004, targetaiplatform.googleapis.com, auth viax-goog-api-keyheaderalwaysBind: true— returns 503 when unconfigured (consistent with Gemini)providers/index.jsalongside the existing four adaptersTypeScript host-side wiring
API_PROXY_PORTS.VERTEX = 10004insrc/types/ports.tsgoogleApiKey?: stringfield onWrapperConfig(readsGOOGLE_API_KEYfrom env, redacted from audit logs)vertexApiTarget?/vertexApiBasePath?routing overrides inApiProxyRoutingOptionsVERTEX_ENVadded to the sharedprovider-env-constants.json(single source of truth for both TS host and JS sidecar)Credential isolation
vertex-credential-env.ts: injectsGOOGLE_VERTEX_BASE_URL=http://api-proxy:10004+GOOGLE_API_KEY=google-api-key-placeholder-for-credential-isolationinto the agent env; real key stays in the sidecar onlyexcluded-vars.ts:GOOGLE_API_KEYandGOOGLE_VERTEX_BASE_URLexcluded from agent env when--enable-api-proxyis activebuildApiProxyBaseEnvforwards realGOOGLE_API_KEYto the sidecar containerValidation / diagnostics
validateApiProxyConfiggains ahasGoogleApiKeyparam; "no keys found" warning and startup log updated to mentionGOOGLE_API_KEY.geminihome dir mount/pre-creation now also triggers ongoogleApiKey(same CLI, same config dir)Usage: export
GOOGLE_API_KEYin the runner env, setGOOGLE_GENAI_USE_VERTEXAI: "true"inengine.env— AWF holds the real key in the sidecar and routes Vertex traffic through the proxy.